Move stream_output to ProcessBuilder
authorAleksey Kladov <aleksey.kladov@gmail.com>
Wed, 14 Sep 2016 18:10:30 +0000 (21:10 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Sat, 17 Sep 2016 11:59:19 +0000 (14:59 +0300)
src/cargo/ops/cargo_rustc/custom_build.rs
src/cargo/ops/cargo_rustc/job_queue.rs
src/cargo/util/process_builder.rs
tests/build-script.rs
tests/build.rs
tests/run.rs

index ffc1aeaab8f15b75f97bc79f96b8bb97058477c2..8835824898c5aafcac90fa5fbcf972ff21636e8f 100644 (file)
@@ -3,16 +3,12 @@ use std::fs;
 use std::path::{PathBuf, Path};
 use std::str;
 use std::sync::{Mutex, Arc};
-use std::process::{Stdio, Output};
 
 use core::PackageId;
-use util::{CargoResult, Human};
+use util::{CargoResult, Human, Freshness};
 use util::{internal, ChainError, profile, paths};
-use util::{Freshness, ProcessBuilder, read2};
-use util::errors::{process_error, ProcessError};
 
 use super::job::Work;
-use super::job_queue::JobState;
 use super::{fingerprint, Kind, Context, Unit};
 use super::CommandType;
 
@@ -209,7 +205,10 @@ fn build_work<'a, 'cfg>(cx: &mut Context<'a, 'cfg>, unit: &Unit<'a>)
         // And now finally, run the build command itself!
         state.running(&p);
         let cmd = p.into_process_builder();
-        let output = try!(stream_output(state, &cmd).map_err(|mut e| {
+        let output = try!(cmd.exec_with_streaming(
+            &mut |out_line| state.stdout(out_line),
+            &mut |err_line| state.stderr(err_line),
+        ).map_err(|mut e| {
             e.desc = format!("failed to run custom build command for `{}`\n{}",
                              pkg_name, e.desc);
             Human(e)
@@ -443,55 +442,3 @@ pub fn build_map<'b, 'cfg>(cx: &mut Context<'b, 'cfg>,
         }
     }
 }
-
-fn stream_output(state: &JobState, cmd: &ProcessBuilder)
-                 -> Result<Output, ProcessError> {
-    let mut stdout = Vec::new();
-    let mut stderr = Vec::new();
-
-    let status = try!((|| {
-        let mut cmd = cmd.build_command();
-        cmd.stdout(Stdio::piped())
-           .stderr(Stdio::piped())
-           .stdin(Stdio::null());
-        let mut child = try!(cmd.spawn());
-        let out = child.stdout.take().unwrap();
-        let err = child.stderr.take().unwrap();
-
-        try!(read2(out, err, &mut |is_out, data, eof| {
-            let idx = if eof {
-                data.len()
-            } else {
-                match data.iter().rposition(|b| *b == b'\n') {
-                    Some(i) => i + 1,
-                    None => return,
-                }
-            };
-            let data = data.drain(..idx);
-            let dst = if is_out {&mut stdout} else {&mut stderr};
-            let start = dst.len();
-            dst.extend(data);
-            let s = String::from_utf8_lossy(&dst[start..]);
-            if is_out {
-                state.stdout(&s);
-            } else {
-                state.stderr(&s);
-            }
-        }));
-        child.wait()
-    })().map_err(|e| {
-        let msg = format!("could not exeute process {}", cmd);
-        process_error(&msg, Some(e), None, None)
-    }));
-    let output = Output {
-        stdout: stdout,
-        stderr: stderr,
-        status: status,
-    };
-    if !output.status.success() {
-        let msg = format!("process didn't exit successfully: {}", cmd);
-        Err(process_error(&msg, None, Some(&status), Some(&output)))
-    } else {
-        Ok(output)
-    }
-}
index a0cb1dddee991a5b523a4c5190f29b9b77fe2cd1..53bad6b786c602e7a11cfbf904bcf63061eceed4 100644 (file)
@@ -170,12 +170,12 @@ impl<'a> JobQueue<'a> {
                 }
                 Message::Stdout(out) => {
                     if cx.config.extra_verbose() {
-                        try!(write!(cx.config.shell().out(), "{}", out));
+                        try!(writeln!(cx.config.shell().out(), "{}", out));
                     }
                 }
                 Message::Stderr(err) => {
                     if cx.config.extra_verbose() {
-                        try!(write!(cx.config.shell().err(), "{}", err));
+                        try!(writeln!(cx.config.shell().err(), "{}", err));
                     }
                 }
                 Message::Finish(result) => {
index d86df727fa3b9afd10899f1981791a0605334945..856e337e200de514e98af0c7d12ecf7c13ee54f9 100644 (file)
@@ -3,9 +3,9 @@ use std::env;
 use std::ffi::{OsString, OsStr};
 use std::fmt;
 use std::path::Path;
-use std::process::{Command, Output};
+use std::process::{Command, Stdio, Output};
 
-use util::{ProcessError, process_error};
+use util::{ProcessError, process_error, read2};
 use util::shell_escape::escape;
 
 #[derive(Clone, PartialEq, Debug)]
@@ -75,7 +75,7 @@ impl ProcessBuilder {
     pub fn exec(&self) -> Result<(), ProcessError> {
         let mut command = self.build_command();
         let exit = try!(command.status().map_err(|e| {
-            process_error(&format!("Could not execute process `{}`",
+            process_error(&format!("could not execute process `{}`",
                                    self.debug_string()),
                           Some(e), None, None)
         }));
@@ -83,7 +83,7 @@ impl ProcessBuilder {
         if exit.success() {
             Ok(())
         } else {
-            Err(process_error(&format!("Process didn't exit successfully: `{}`",
+            Err(process_error(&format!("process didn't exit successfully: `{}`",
                                        self.debug_string()),
                               None, Some(&exit), None))
         }
@@ -93,7 +93,7 @@ impl ProcessBuilder {
         let mut command = self.build_command();
 
         let output = try!(command.output().map_err(|e| {
-            process_error(&format!("Could not execute process `{}`",
+            process_error(&format!("could not execute process `{}`",
                                self.debug_string()),
                           Some(e), None, None)
         }));
@@ -101,12 +101,69 @@ impl ProcessBuilder {
         if output.status.success() {
             Ok(output)
         } else {
-            Err(process_error(&format!("Process didn't exit successfully: `{}`",
+            Err(process_error(&format!("process didn't exit successfully: `{}`",
                                        self.debug_string()),
                               None, Some(&output.status), Some(&output)))
         }
     }
 
+    pub fn exec_with_streaming(&self,
+                               on_stdout_line: &mut FnMut(&str),
+                               on_stderr_line: &mut FnMut(&str))
+                               -> Result<Output, ProcessError> {
+        let mut stdout = Vec::new();
+        let mut stderr = Vec::new();
+
+        let mut cmd = self.build_command();
+        cmd.stdout(Stdio::piped())
+            .stderr(Stdio::piped())
+            .stdin(Stdio::null());
+
+        let status = try!((|| {
+            let mut child = try!(cmd.spawn());
+            let out = child.stdout.take().unwrap();
+            let err = child.stderr.take().unwrap();
+            try!(read2(out, err, &mut |is_out, data, eof| {
+                let idx = if eof {
+                    data.len()
+                } else {
+                    match data.iter().rposition(|b| *b == b'\n') {
+                        Some(i) => i + 1,
+                        None => return,
+                    }
+                };
+                let data = data.drain(..idx);
+                let dst = if is_out {&mut stdout} else {&mut stderr};
+                let start = dst.len();
+                dst.extend(data);
+                for line in String::from_utf8_lossy(&dst[start..]).lines() {
+                    if is_out {
+                        on_stdout_line(line)
+                    } else {
+                        on_stderr_line(line)
+                    }
+                }
+            }));
+            child.wait()
+        })().map_err(|e| {
+            process_error(&format!("could not execute process `{}`",
+                                   self.debug_string()),
+                          Some(e), None, None)
+        }));
+        let output = Output {
+            stdout: stdout,
+            stderr: stderr,
+            status: status,
+        };
+        if !output.status.success() {
+            Err(process_error(&format!("process didn't exit successfully: `{}`",
+                                       self.debug_string()),
+                              None, Some(&output.status), Some(&output)))
+        } else {
+            Ok(output)
+        }
+    }
+
     pub fn build_command(&self) -> Command {
         let mut command = Command::new(&self.program);
         if let Some(cwd) = self.get_cwd() {
index f471f5475b9a942df022d731be198d2ec30f0a1f..e0669311039323f92a550c3a6138fb05ad03cda3 100644 (file)
@@ -715,7 +715,7 @@ fn build_deps_not_for_normal() {
 [ERROR] Could not compile `foo`.
 
 Caused by:
-  Process didn't exit successfully: [..]
+  process didn't exit successfully: [..]
 "));
 }
 
index 4844eae5362d1c83c419fc78d10f21d970b7aaf2..5657396382cc37d5400e0c1dbdd849c09ae3ff09 100644 (file)
@@ -1967,7 +1967,7 @@ fn rustc_env_var() {
                  .env("RUSTC", "rustc-that-does-not-exist").arg("-v"),
                 execs().with_status(101)
                        .with_stderr("\
-[ERROR] Could not execute process `rustc-that-does-not-exist -vV` ([..])
+[ERROR] could not execute process `rustc-that-does-not-exist -vV` ([..])
 
 Caused by:
 [..]
index 1f76df20dcdae9f2f28698a6d0bfe0b515d338e9..7c769c2451506557ee513ab699c9895889ace842 100644 (file)
@@ -132,7 +132,7 @@ fn exit_code() {
 [COMPILING] foo v0.0.1 (file[..])
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..]
 [RUNNING] `target[..]`
-[ERROR] Process didn't exit successfully: `target[..]foo[..]` (exit code: 2)
+[ERROR] process didn't exit successfully: `target[..]foo[..]` (exit code: 2)
 "));
 }
 
@@ -156,7 +156,7 @@ fn exit_code_verbose() {
 [RUNNING] `rustc [..]`
 [FINISHED] debug [unoptimized + debuginfo] target(s) in [..]
 [RUNNING] `target[..]`
-[ERROR] Process didn't exit successfully: `target[..]foo[..]` (exit code: 2)
+[ERROR] process didn't exit successfully: `target[..]foo[..]` (exit code: 2)
 "));
 }